/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package socof_trab1;

import dbaccess.Ficheiro;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class DownloadersLaucher extends Thread {

    private static final int DOWNLOADERS_LIMIT = 10;
    private static final int MAX_BANDWIDTH_ALLOCATION = 800000;
    private ResizeableSemaphore maxDownloaders = new ResizeableSemaphore(0);
    private ExecutorService tpDownloaders = Executors.newCachedThreadPool();
    private static DownloadersLaucher lb = new DownloadersLaucher();
    private long maxBandwidthAllocation = MAX_BANDWIDTH_ALLOCATION;
    private int downloadersLimit = DOWNLOADERS_LIMIT;

    private DownloadersLaucher() {
    }

    public static DownloadersLaucher getInstance() {
        return DownloadersLaucher.lb;
    }

    public void setMaxExecutors(int maxDownloaders) {
        this.maxDownloaders.resizeIfRequired(maxDownloaders);
    }

    public synchronized void setDownloadersLimit(int downloadersLimit) {
        this.downloadersLimit = downloadersLimit;
    }

    @Override
    public void run() {
        // Starts bandwith controller
        DownloadersController.getInstance().start();

        try {
            tpDownloaders = Executors.newCachedThreadPool();
            while (!isInterrupted()) {
                Runnable downloader = new ExecutorDownloader(maxDownloaders);
                tpDownloaders.execute(downloader);
            }
        } catch (InterruptedException ex) {
        } finally {
            processInterruption();
        }
    }

    private void processInterruption() {
        try {
            DownloadersController.getInstance().interrupt();

            tpDownloaders.shutdown();
            tpDownloaders.awaitTermination(10, TimeUnit.SECONDS);
        } catch (InterruptedException ex) {
        }
    }

    /**
     * Allows user to set the max bandwidth allocation
     *
     * @param size
     */
    public synchronized void setMaxBandwidthAllocation(long size) {
        this.maxBandwidthAllocation = size;
    }

    public synchronized long getMaxBandwidthAllocation() {
        return this.maxBandwidthAllocation;
    }

    public void decreaseDownloaders() {
        if (maxDownloaders.getTotalPermits() > 1) {
            maxDownloaders.removePermit();
        }
    }

    public void increaseDownloaders() {
        if (maxDownloaders.getTotalPermits() < downloadersLimit) {
            maxDownloaders.addPermit();
        }
    }
}
